//UMASS Lowell
//SW Engineering
//Spring 2010
//Project: BUFDB - Setup component
//Version: 3
//Author: Chuck DeLoid
//Date: 5/4/10
//Purpose: A C++ program that uses the PostgreSQL libpq to connect to a postgreSQL //database server and create a database

#include <boost/algorithm/string/join.hpp>
#include <boost/program_options.hpp>

using namespace boost;
namespace po = boost::program_options;

#include <google/protobuf/message.h>
#include <google/protobuf/descriptor.h>

#include <iostream>  
#include <string>

#include <libpq-fe.h>
#include <libpq/libpq-fs.h>

#include "bufferSetup.h"
#include "database.pb.h"



////////////////////////////////////////////////////////////////////////////////
// parse_arguments()
//
// Description: This function will prompt user for connection parameters from  
//		the command line.
// Inputs: argc, argv
// 
//
// Outputs: none
//
// Return: conn_args
/////////////////////////////////////////////////////////////////////////////////
// parse the command line arguments into a dictionary
map<string, string> parse_arguments(int argc, char* argv[]) {

    po::options_description desc("Allowed options");
    desc.add_options()
        ("help,h", "produce help message")
        ("host", po::value<string>(), "host")
        ("port", po::value<string>(), "port number")
        ("dbname,d", po::value<string>(), "database name")
        ("user,U", po::value<string>(), "user name")
        ("password,p", po::value<string>(), "password")
        ("timeout,t", po::value<string>(), "timeout (s)")
    ;

    po::variables_map vm;
    po::store(po::parse_command_line(argc, argv, desc), vm);
    po::notify(vm);

    if (vm.count("help")) {
        cout << desc << endl;
        exit(1);
    }

    map<string, string> conn_args;
    conn_args["port"] = vm.count("port") ? vm["port"].as<string>() : "5432";
    conn_args["host"] = vm.count("host") ? vm["host"].as<string>() : "localhost";
    conn_args["dbname"] = vm.count("dbname") ? vm["dbname"].as<string>() : "postgres";
    conn_args["user"] = vm.count("user") ? vm["user"].as<string>() : "postgres";
    conn_args["password"] = 
        vm.count("password") ? vm["password"].as<string>() : "Kollsman1";
    conn_args["connect_timeout"] = 
        vm.count("connect_timeout") ? vm["connect_timeout"].as<string>() : "10";

    return conn_args;
}




////////////////////////////////////////////////////////////////////////////////
// connect()
//
// Description: This function will read connection parameter that are input by user
// Inputs: argc, argv
// 
//
// Outputs: none
//
// Return: con
/////////////////////////////////////////////////////////////////////////////////
PGconn *connect(int argc, char* argv[]) {
    map<string, string> conn_args = parse_arguments(argc, argv);

    // create pairs of arguments with the form: "key = 'value'"
    vector<string> kvs;
    map<string, string>::iterator p;
    for (p=conn_args.begin(); p!=conn_args.end(); p++) {
        kvs.push_back(p->first + " = '" + p->second + "'");
    }
    
    // join the pairs together with a space
    string coninfo = algorithm::join(kvs, " ");

    PGconn *con = PQconnectdb(coninfo.c_str());

    //Connection parameters Server = localhost, Database = postgres, port =5432,
    //username = postgres, password = Kollsman1
    if (!con) {
        cerr << "libpq error: PQconnectdb returned NULL." << endl;
        exit(0);
    }

    if (PQstatus(con) != CONNECTION_OK) {
        cerr << "libpq error: PQstatus(con) != CONNECTION_OK" << endl;
        exit(0);
    } 

    return con;
}
